/*
 * Copyright (C) 2015 - 2019 Xilinx, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 */
/*
* platform_zynqmp.c
*
* ZynqMP platform specific functions.
*
*
* </pre>
 */

#if defined (__arm__) || defined (__aarch64__)

#include "xparameters.h"
#include "xparameters_ps.h"	/* defines XPAR values */
#include "xil_cache.h"
#include "xscugic.h"
#include "platform.h"
#include "platform_config.h"
#include "sys.h"
#if defined(PLATFORM_ZYNQMP) || defined(PLATFORM_VERSAL)
#include "xttcps.h"
#include "xplatform_info.h"
#include "dri_hal_uart_lite.h"
#include "dri_hal_uart.h"
#include "fpga_reg.h"
#include "dri_hal_can.h"
#include "tele_data_transfer.h"
#include "sys_monitor.h"
#define INTC_DEVICE_ID		XPAR_SCUGIC_SINGLE_DEVICE_ID
#define TIMER_DEVICE_ID		XPAR_XTTCPS_0_DEVICE_ID
#define TIMER_IRPT_INTR		XPAR_XTTCPS_0_INTR
#define INTC_BASE_ADDR		XPAR_SCUGIC_0_CPU_BASEADDR
#define INTC_DIST_BASE_ADDR	XPAR_SCUGIC_0_DIST_BASEADDR

#define CAN_WAIT_DELAY      4       /*  链路等待延时/秒    */

#define PLATFORM_TIMER_INTR_RATE_HZ (2000)
static uint8_t BaseTime2khz_flag = OFF;

static XTtcPs TimerInstance;
static XInterval Interval;
static u8 Prescaler;
XScuGic IntcInstance;
void platform_clear_interrupt( XTtcPs * TimerInstance );

void timer_callback(XTtcPs * TimerInstance)
{
	BaseTime2khz_flag = ON;
	platform_clear_interrupt(TimerInstance);
}

u8 GetBaseTime2khzScheduler(void)
{
	if(BaseTime2khz_flag == ON)
	{
		BaseTime2khz_flag = OFF;
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

void platform_setup_timer(void)
{
	XTtcPs * Timer = &TimerInstance;
	XTtcPs_Config *Config;
	Config = XTtcPs_LookupConfig(TIMER_DEVICE_ID);
	XTtcPs_CfgInitialize(Timer, Config, Config->BaseAddress);
	XTtcPs_SetOptions(Timer, XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE);
	XTtcPs_CalcIntervalFromFreq(Timer, PLATFORM_TIMER_INTR_RATE_HZ, &Interval, &Prescaler);
	XTtcPs_SetInterval(Timer, Interval);
	XTtcPs_SetPrescaler(Timer, Prescaler);
}

void platform_clear_interrupt( XTtcPs * TimerInstance )
{
	XTtcPs_GetInterruptStatus(TimerInstance);
	XTtcPs_ClearInterruptStatus(TimerInstance, StatusEvent);
}

void platform_setup_interrupts(void)
{

	Xil_ExceptionInit();
	/*
	 * Connect the interrupt controller interrupt handler to the hardware
	 * interrupt handling logic in the processor.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
			(Xil_ExceptionHandler)XScuGic_DeviceInterruptHandler,
			(void *)INTC_DEVICE_ID);
	/*
	 * Connect the device driver handler that will be called when an
	 * interrupt for the device occurs, the handler defined above performs
	 * the specific interrupt processing for the device.
	 */
	XScuGic_RegisterHandler(INTC_BASE_ADDR, TIMER_IRPT_INTR,
					(Xil_ExceptionHandler)timer_callback,
					(void *)&TimerInstance);
	/*
	 * Enable the interrupt for scu timer.
	 */
	XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, TIMER_IRPT_INTR);

	return;
}

void platform_enable_interrupts()
{
	/*
	 * Enable non-critical exceptions.
	 */

 	PsCanInterruptSet(&IntcInstance,&Can0, CAN0_INTR_ID);
 	PsCanInterruptSet(&IntcInstance,&Can1, CAN1_INTR_ID);

	Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
	XScuGic_EnableIntr(INTC_DIST_BASE_ADDR, TIMER_IRPT_INTR);
	XTtcPs_EnableInterrupts(&TimerInstance, XTTCPS_IXR_INTERVAL_MASK);
	XTtcPs_Start(&TimerInstance);
	return;
}



void init_platform()
{
	u8 iStatus = 0;
	platform_setup_timer();
	iStatus = UartPsIntrInit(&InterruptController, &UartPs_0,UART_0_DEVICE_ID, UART_0_INT_IRQ_ID);//用于assist_fpga通信
	g_tEquipmentStatus.equipInitStatus = iStatus;
    #ifdef USE_DEBUG
	UartPsIntrInit(&InterruptController, &UartPs_1,UART_1_DEVICE_ID, UART_1_INT_IRQ_ID);//用于debug
    #endif
	iStatus = UartLiteIntrInit(&IntcInstance, &UartLiteInst0,UARTLITE0_DEVICE_ID, UARTLITE0_IRPT_INTR);//用于与camera1通信
	g_tEquipmentStatus.equipInitStatus|=(iStatus << 1);
	iStatus = UartLiteIntrInit(&IntcInstance, &UartLiteInst1,UARTLITE1_DEVICE_ID, UARTLITE1_IRPT_INTR);//用于与camera2通信
    g_tEquipmentStatus.equipInitStatus|=(iStatus << 2);
	iStatus = PsCanInit(CAN0_DEVICE_ID, &Can0, &IntcInstance, CAN0_INTR_ID);
    g_tEquipmentStatus.equipInitStatus|=(iStatus << 3);
	iStatus = PsCanInit(CAN1_DEVICE_ID, &Can1, &IntcInstance, CAN1_INTR_ID);
    g_tEquipmentStatus.equipInitStatus|=(iStatus << 4);
	platform_setup_interrupts();
	return;
}
void can_config()
{
    can_conf.can_bc_interval++;

    if(can_conf.can_wait_cnt > CAN_WAIT_DELAY)
    {
        can_conf.can0_rst_flag = 1;
        can_conf.can1_rst_flag = 1;
        can_conf.can_wait_cnt = 0;
    }
    else can_conf.can_wait_cnt++;

    if(can_conf.can0_rst_flag && (!PsCanInit(CAN0_DEVICE_ID, &Can0, &IntcInstance, CAN0_INTR_ID)))
        can_conf.can0_rst_flag = 0;

    if(can_conf.can1_rst_flag && (!PsCanInit(CAN1_DEVICE_ID, &Can1, &IntcInstance, CAN0_INTR_ID)))
        can_conf.can1_rst_flag = 0;
}

void cleanup_platform()
{
	Xil_ICacheDisable();
	Xil_DCacheDisable();
	return;
}
#endif
#endif
